import java.lang.ref.PhantomReference;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.TimeUnit;

public class CustomThreadPoolExecutor {
    private final int corePoolSize;
    private final int maximumPoolSize;
    private final long keepAliveTime;
    private final TimeUnit unit;
    private final BlockingQueue<Runnable> workQueue;
    private final RejectedExecutionHandler handler;

    private volatile boolean isShutDown = false;

    private int currentPoolSize = 0;
    /**
     * 构造方法
     * @param corePoolSize
     * @param maximumPoolSize
     * @param keepAliveTime
     * @param unit
     * @param workQueue
     * @param handler
     */
    public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.keepAliveTime = keepAliveTime;
        this.unit = unit;
        this.workQueue = workQueue;
        this.handler = handler;
    }

    /**
     * 提交任务
     * @param task
     */
    public void execute(Runnable task) {
        if (isShutDown) {
            throw new IllegalStateException("ThreadPool is shut down");
        }

        synchronized (this) {
            //如果当前线程小于核心线程，直接创建新线程
            if (currentPoolSize < corePoolSize) {
                new Worker(task).start();
                currentPoolSize++;
                return;
            }

            //尝试将任务加入队列
            if (!workQueue.offer(task)) {
                if (currentPoolSize < maximumPoolSize) {
                    new Worker(task).start();
                    currentPoolSize++;
                } else {
                    handler.rejectedExecution(task,null);
                }
            }
        }
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        isShutDown = true;
    }

    /**
     * 工作任务
     */
    private class Worker extends Thread {
        private Runnable task;

        Worker(Runnable task) {
            this.task = task;
        }

        @Override
        public void run() {
            while(true) {
                try {
                    if (!(task != null || (task = getTask()) != null)) break;
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                try {
                    task.run();
                } finally {
                    task = null;
                }
            }
        }

        /**
         * 从队列中获取任务
         * @return
         */
        private Runnable getTask() throws InterruptedException {
            return workQueue.poll(keepAliveTime,unit);
        }
    }


}
